<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket 心跳测试工具</title>
    <script src="https://cdn.jsdelivr.net/npm/websocket-heartbeat-js@0.0.1/dist/websocket-heartbeat.min.js"></script>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: #fff;
            min-height: 100vh;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .container {
            width: 100%;
            max-width: 900px;
            background: rgba(0, 0, 20, 0.8);
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            overflow: hidden;
        }

        header {
            background: rgba(0, 0, 30, 0.9);
            padding: 20px;
            text-align: center;
            border-bottom: 1px solid #00b4ff;
        }

        h1 {
            font-size: 2.2rem;
            margin-bottom: 10px;
            background: linear-gradient(90deg, #00b4ff, #00ff9d);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            text-shadow: 0 0 10px rgba(0, 180, 255, 0.3);
        }

        .subtitle {
            color: #aaa;
            font-size: 1rem;
        }

        .config-panel {
            padding: 20px;
            background: rgba(10, 20, 40, 0.6);
            border-bottom: 1px solid #2a3a6c;
        }

        .input-group {
            margin-bottom: 15px;
        }

        label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
            color: #00b4ff;
        }

        input {
            width: 100%;
            padding: 12px 15px;
            border-radius: 8px;
            border: 1px solid #2a3a6c;
            background: rgba(0, 10, 30, 0.8);
            color: #fff;
            font-size: 1rem;
            transition: all 0.3s;
        }

        input:focus {
            outline: none;
            border-color: #00b4ff;
            box-shadow: 0 0 10px rgba(0, 180, 255, 0.5);
        }

        .btn-group {
            display: flex;
            gap: 15px;
            margin-top: 20px;
        }

        button {
            flex: 1;
            padding: 12px;
            border: none;
            border-radius: 8px;
            font-size: 1rem;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s;
        }

        .connect-btn {
            background: linear-gradient(90deg, #00c853, #009624);
            color: white;
        }

        .disconnect-btn {
            background: linear-gradient(90deg, #ff1744, #d50000);
            color: white;
        }

        .send-btn {
            background: linear-gradient(90deg, #2979ff, #2962ff);
            color: white;
        }

        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
        }

        button:active {
            transform: translateY(1px);
        }

        button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }

        .connection-status {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 10px 0;
        }

        .status-indicator {
            width: 15px;
            height: 15px;
            border-radius: 50%;
            background: #ff1744;
        }

        .status-indicator.connected {
            background: #00c853;
            box-shadow: 0 0 10px #00c853;
        }

        .status-text {
            font-weight: bold;
        }

        .panels {
            display: flex;
            padding: 20px;
            gap: 20px;
        }

        .message-panel, .log-panel {
            flex: 1;
            background: rgba(10, 20, 40, 0.6);
            border-radius: 10px;
            padding: 20px;
            height: 300px;
            display: flex;
            flex-direction: column;
        }

        .panel-title {
            margin-bottom: 15px;
            color: #00b4ff;
            font-size: 1.2rem;
        }

        #message-input {
            flex: 1;
            resize: none;
            padding: 15px;
            background: rgba(0, 10, 30, 0.8);
            border: 1px solid #2a3a6c;
            border-radius: 8px;
            color: #fff;
            font-size: 1rem;
            margin-bottom: 15px;
        }

        #message-input:focus {
            outline: none;
            border-color: #00b4ff;
            box-shadow: 0 0 10px rgba(0, 180, 255, 0.5);
        }

        #log {
            flex: 1;
            background: rgba(0, 10, 30, 0.8);
            border: 1px solid #2a3a6c;
            border-radius: 8px;
            padding: 15px;
            overflow-y: auto;
            font-family: monospace;
            font-size: 0.9rem;
            color: #ddd;
        }

        .log-entry {
            margin-bottom: 8px;
            padding-bottom: 8px;
            border-bottom: 1px solid #2a3a6c;
        }

        .timestamp {
            color: #00b4ff;
            margin-right: 10px;
        }

        .sent {
            color: #00c853;
        }

        .received {
            color: #2979ff;
        }

        .system {
            color: #ff9800;
        }

        .error {
            color: #ff1744;
        }

        .heartbeat {
            color: #aa00ff;
        }

        footer {
            text-align: center;
            padding: 20px;
            color: #aaa;
            font-size: 0.9rem;
            border-top: 1px solid #2a3a6c;
        }

        @media (max-width: 768px) {
            .panels {
                flex-direction: column;
            }
        }
    </style>
</head>
<body>
<div class="container">
    <header>
        <h1>WebSocket 心跳测试工具</h1>
        <p class="subtitle">使用WebsocketHeartbeatJs实现稳定连接与心跳检测</p>
    </header>

    <div class="config-panel">
        <div class="input-group">
            <label for="ws-url">WebSocket URL:</label>
            <input type="text" id="ws-url" placeholder="wss://echo.websocket.org" value="wss://echo.websocket.org">
        </div>

        <div class="connection-status">
            <div class="status-indicator" id="status-indicator"></div>
            <span class="status-text" id="status-text">未连接</span>
        </div>

        <div class="btn-group">
            <button id="connect-btn" class="connect-btn">连接</button>
            <button id="disconnect-btn" class="disconnect-btn" disabled>断开</button>
        </div>
    </div>

    <div class="panels">
        <div class="message-panel">
            <h3 class="panel-title">发送消息</h3>
            <textarea id="message-input" placeholder="输入要发送的消息..."></textarea>
            <button id="send-btn" class="send-btn" disabled>发送消息</button>
        </div>

        <div class="log-panel">
            <h3 class="panel-title">连接日志</h3>
            <div id="log"></div>
        </div>
    </div>

    <footer>
        <p>WebsocketHeartbeatJs 测试页面 | 支持断线自动重连与心跳检测</p>
    </footer>
</div>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        // 获取DOM元素
        const wsUrlInput = document.getElementById('ws-url');
        const connectBtn = document.getElementById('connect-btn');
        const disconnectBtn = document.getElementById('disconnect-btn');
        const sendBtn = document.getElementById('send-btn');
        const messageInput = document.getElementById('message-input');
        const logElement = document.getElementById('log');
        const statusIndicator = document.getElementById('status-indicator');
        const statusText = document.getElementById('status-text');

        let websocket = null;

        // 添加日志
        function addLog(message, type = 'system') {
            const now = new Date();
            const timestamp = `[${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}]`;
            const logEntry = document.createElement('div');
            logEntry.className = `log-entry ${type}`;
            logEntry.innerHTML = `<span class="timestamp">${timestamp}</span> ${message}`;
            logElement.appendChild(logEntry);
            logElement.scrollTop = logElement.scrollHeight;
        }

        // 更新连接状态
        function updateConnectionStatus(connected) {
            if (connected) {
                statusIndicator.classList.add('connected');
                statusText.textContent = '已连接';
                connectBtn.disabled = true;
                disconnectBtn.disabled = false;
                sendBtn.disabled = false;
            } else {
                statusIndicator.classList.remove('connected');
                statusText.textContent = '未连接';
                connectBtn.disabled = false;
                disconnectBtn.disabled = true;
                sendBtn.disabled = true;
            }
        }

        // 初始化WebSocket连接
        function initWebSocket() {
            const url = wsUrlInput.value.trim();
            if (!url) {
                addLog('请输入有效的WebSocket URL', 'error');
                return;
            }

            // 销毁现有连接
            if (websocket) {
                websocket.close();
            }

            addLog(`正在连接: ${url}`);

            // 创建WebSocketHeartbeat实例
            websocket = new WebsocketHeartbeat({
                url: url,
                pingTimeout: 5000,
                pongTimeout: 10000,
                reconnectTimeout: 5000,
                pingMsg: '{"type":"ping"}'
            });

            // 事件处理
            websocket.onopen = () => {
                addLog('连接已建立', 'system');
                updateConnectionStatus(true);
            };

            websocket.onmessage = (e) => {
                if (e.data === '{"type":"pong"}') {
                    addLog('收到心跳响应', 'heartbeat');
                } else {
                    addLog(`收到消息: ${e.data}`, 'received');
                }
            };

            websocket.onreconnect = () => {
                addLog('正在尝试重新连接...', 'system');
            };

            websocket.onclose = () => {
                addLog('连接已关闭', 'system');
                updateConnectionStatus(false);
            };
        }

        // 连接按钮事件
        connectBtn.addEventListener('click', initWebSocket);

        // 断开连接按钮事件
        disconnectBtn.addEventListener('click', function() {
            if (websocket) {
                websocket.close();
                addLog('已主动断开连接', 'system');
            }
        });

        // 发送消息按钮事件
        sendBtn.addEventListener('click', function() {
            const message = messageInput.value.trim();
            if (!message) {
                addLog('请输入要发送的消息', 'error');
                return;
            }

            if (websocket) {
                websocket.send(message);
                addLog(`发送消息: ${message}`, 'sent');
                messageInput.value = '';
            }
        });

        // 支持按Enter键发送消息
        messageInput.addEventListener('keypress', function(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendBtn.click();
            }
        });

        // 添加初始日志
        addLog('页面已加载，请输入WebSocket URL并点击连接');
        addLog('示例URL: wss://echo.websocket.org');
    });
</script>
</body>
</html>